Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

253
Vistas
Advertencia "Lista virtualizada: tiene una lista grande que tarda en actualizarse" aunque todos los componentes están optimizados

He tenido muchos problemas para evitar recibir la advertencia "Lista virtualizada: tiene una lista grande que tarda en actualizarse" al usar un componente <FlatList> con React-Native.

Ya investigué mucho y busqué en Google-Fu para probar una solución, pero ninguna de las soluciones ayudó, ni siquiera la solución en este problema de GitHub .

Cosas a tener en cuenta:

  • Estoy usando shouldComponentUpdate() { return false; } en mi componente Elemento de lista, por lo que no se actualizan en absoluto.
  • El componente que representa FlatList ya es un PureComponent
  • Agregué console.logs en los métodos de procesamiento de mis componentes y puedo confirmar que no se vuelven a procesar.
  • No estoy usando funciones anónimas, por lo que el componente renderItem no se reinicializa en cada llamada.

Importante : la advertencia solo parece ocurrir después de cambiar a una pestaña separada usando mi BottomTabNavigator y luego regresar y desplazarse por mi lista; pero esto es confuso porque cuando hago esto, el componente de pantalla FlatList no se vuelve a representar y tampoco los elementos de la lista. Dado que los componentes no se vuelven a renderizar cuando se navega a otra pestaña, ¿por qué sucedería este error?

Aquí está mi código exacto:

Aplicación.tsx

 const AppRoutes = [ { name: "Home", Component: HomeScreen }, { name: "Catalog", Component: CatalogScreen }, { name: "Cart", Component: CartScreen } ]; export const StoreApp = () => { return ( <NavigationContainer> <StatusBar barStyle="dark-content" /> <Tabs.Navigator> {AppRoutes.map((route, index) => <Tabs.Screen key={index} name={route.name} component={route.Component} options={{ headerShown: (route.name !== "Home") ?? false, tabBarIcon: props => <TabIcon icon={route.name} {...props} /> }} /> )} </Tabs.Navigator> </NavigationContainer> ); };

CatalogScreen.tsx

 import React from "react"; import { FlatList, SafeAreaView, Text, View, StyleSheet } from "react-native"; import { LoadingSpinnerOverlay } from "../components/LoadingSpinnerOverlay"; import { getAllProducts, ProductListData } from "../api/catalog"; class ProductItem extends React.Component<{ item: ProductListData }> { shouldComponentUpdate() { return false; } render() { return ( <View> {console.log(`Rendered ${this.props.item.name}-${Math.random()}`)} <Text style={{height: 100}}>{this.props.item.name}</Text> </View> ); } } export class CatalogScreen extends React.PureComponent { state = { productData: [] }; componentDidMount() { getAllProducts() .then(response => { this.setState({ productData: response.data }); }) .catch(err => { console.log(err); }); } private renderItem = (props: any) => <ProductItem {...props} />; private keyExtractor = (product: any) => `${product.id}`; private listItemLayout = (data: any, index: number) => ({ length: 100, offset: 100 * index, index }); render() { const { productData } = this.state; console.log("CATALOG RENDERED"); return ( <SafeAreaView style={styles.pageView}> {!productData.length && <LoadingSpinnerOverlay text="Loading products..." />} <View style={{backgroundColor: "red", height: "50%"}}> <FlatList data={productData} removeClippedSubviews keyExtractor={this.keyExtractor} renderItem={this.renderItem} getItemLayout={this.listItemLayout} /> </View> </SafeAreaView> ); } }; const styles = StyleSheet.create({ pageView: { height: "100%", position: "relative", } });

Dado que mis componentes y listas están optimizados y sigo recibiendo el error, estoy empezando a creer que esto puede ser un problema real con React Native, pero si alguien puede ver lo que estoy haciendo mal o alguna solución alternativa, esto sería de gran ayuda!

Hallazgos adicionales: encontré que la advertencia ya no ocurre si el componente CatalogScreen está contenido dentro de un NativeStackNavigator con una sola pantalla. Creo que esto puede indicar que se trata de un problema con el módulo BottomTabNavigator .

Por ejemplo, ya no aparece ninguna advertencia si realizo los siguientes cambios:

Aplicación.tsx

 const AppRoutes = [ { name: "Home", Component: HomeScreen }, { name: "Catalog", Component: CatalogPage }, // Changed CatalogScreen to CatalogPage { name: "Cart", Component: CartScreen } ];

CatalogScreen.tsx

 const Stack = createNativeStackNavigator(); export class CatalogPage extends React.PureComponent { render() { return ( <Stack.Navigator> <Stack.Screen name="CatalogStack" options={{ headerShown: false }} component={CatalogScreen} /> </Stack.Navigator> ); } }

Con esta solución alternativa, renderizo el componente Stack Navigation en lugar del componente CatalogScreen directamente. Esto resuelve el problema, pero no entiendo por qué esto haría una diferencia. ¿React Native maneja los objetos de memoria de manera diferente en las pantallas de Stack Navigation en comparación con las pantallas de BottomTabNavigator?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Solo voy a intentar una respuesta al azar, pero en el mejor de los casos es una conjetura.

El video que ha vinculado en los comentarios a su pregunta dejó mucho más claro lo que está sucediendo, algo extraño está sucediendo allí.

Con listas normales como esas, especialmente en dispositivos móviles, desea renderizar y cargar solo los elementos que se muestran y son visibles actualmente, no desea mantener la lista completa de todos los elementos posibles en la memoria y renderizados todo el tiempo. Es por eso que usaría algo como una devolución de llamada para representar el elemento, de modo que la lista pueda invocar la devolución de llamada a medida que se desplaza y mostrar solo los elementos que necesita.

Dicho esto, aquí hay un par de cosas aleatorias que se me ocurren:

  • Asegúrese de que todos los componentes, incluido y especialmente el componente del elemento, sean componentes puros para que no se vuelvan a procesar. Asegúrese de que el componente del elemento no se vuelva a representar.
  • Intente alterar la estructura de sus accesorios para que reciba directamente los accesorios, es decir, ({prop1, prop2}) en lugar de props con ...props . Si desestructura los accesorios de esa manera, se creará un nuevo objeto cada vez que se cargue un elemento. Este podría ser uno de los culpables de su problema, si la lista plana invoca constantemente la devolución de llamada y crea toneladas de objetos nuevos. Esto también podría ser un problema potencial para el artículo del producto, si ve que recibió una nueva referencia de utilería, lo que significa que es un objeto diferente, entonces tendrá que hacer una comparación superficial (incluso si es un componente puro), en cientos de accesorios Eso realmente podría ralentizarlo. El resultado es que en realidad no lo volverá a renderizar, pero seguirá haciendo cientos de comparaciones superficiales de objetos, lo cual es un proceso lento. Así que solucione la desestructuración, apostaría a que algo como esto está causando el problema de rendimiento.
  • Asegúrese de no renderizar dos veces la vista, no renderizar la lista plana antes de que los datos se carguen realmente, antes de que se haya configurado el estado, solo devuelva el control giratorio o el cargador alternativo y, una vez que se haya configurado el estado, devuelva el elemento secundario completo . De lo contrario, está procesando todo el proceso por duplicado, incluso si no hay datos.
  • Pruebe y vea si hace una diferencia si usa una función anónima como devolución de llamada de renderItem, en lugar de usar funciones de clase de reacción. No creo que deba hacer una diferencia, pero vale la pena intentarlo si nada más ayuda, ya que no estoy seguro de cómo el renderItem está utilizando this .

Si todo lo demás falla, le sugiero que pregunte reaccionar nativo en github y, mientras tanto, intente usar una alternativa si hay una. Por otro lado, realmente no veo ningún problema de rendimiento en el video, por lo que quizás también sea un error que se puede ignorar de manera segura.

over 4 years ago · Santiago Trujillo Denunciar

0

Este es un viejo problema con FlatLists en React Native. FlatList en React Native no es conocido por su rendimiento. Sin embargo, esto podría mitigarse comprobando si hay renderizaciones innecesarias o componentes anidados dentro de FlatList y asegurándose de que su FlatList no esté anidada por un ScrollView. Pero ya indicó que no está volviendo a renderizar la lista cuando regresa a la pantalla y no está anidada por ScrollView, por lo que probablemente sea el componente en sí.

Honestamente, recientemente tuve el mismo problema que tú, pero mi FlatList es más complejo que el tuyo. Cuando lo ejecuté en un dispositivo real, noté que no había tenido ningún problema, para mí esto solo fue un problema en Expo Go. He hecho mi parte de investigación, pero no he dado en el clavo, así que solo puedo ofrecer sugerencias.

Sugerencia 1

Echa un vistazo a este paquete RecyclerListView , parece muy prometedor.

sugerencia 2

También existe este paquete, pero soy un poco escéptico acerca de este, he escuchado quejas sobre el paquete React Native Optimized Flatlist . Estoy bastante seguro de que lo probé y no hizo nada para mí.

Además, echa un vistazo a estas dos páginas sobre el tema:

  • Consejos de rendimiento de FlatList
  • Problema de GitHub n.º 13413
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda